#! /usr/bin/env python2
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2019 crane <crane@gosun>
#
# Distributed under terms of the MIT license.

"""

"""

import random
import math
import numpy


pi2 = math.pi * 2


def random_sign():
    sign = random.uniform(0, 1)
    if sign > 0.5:
        return -1
    else:
        return 1

def random_circle_point(radius=1):
    # 随机获取圆上一点
    x = random.uniform(0, radius)
    y = math.sqrt(radius**2 - x*x)
    return random_sign() * x, random_sign() * y

def n_circle_point(n):
    # 随机获取n个圆上的点
    l = []
    for i in range(n):
       l.append(random_circle_point())

    return l

def minus_to_int(n1, n2):
    # cmp返回值必须是int, 这里把相减后的值转换为int
    if n1 - n2 > 0:
        return 1
    if n1 - n2 < 0:
        return -1
    return 0

def point_cmp(p1, p2):
    # 圆上的点顺时针比较: 从first quadrant开始, 到forth quadrant结束
    x1, y1 = p1
    x2, y2 = p2

    if y1 > 0 and y2 > 0:
        # return x2-x1
        return minus_to_int(x2, x1)

    if y1 <0 and y2 < 0:
        # return x1 - x2
        return minus_to_int(x1, x2)

    # return y2 - y1
    return minus_to_int(y2, y1)

def point_cmp_from_3(p1, p2):
    # 从第3象限开始
    x1, y1 = p1
    x2, y2 = p2

    if y1 > 0 and y2 > 0:
        # return x2-x1
        return minus_to_int(x2, x1)

    if y1 <0 and y2 < 0:
        # return x1 - x2
        return minus_to_int(x1, x2)

    # return y2 - y1
    # return minus_to_int(y2, y1)
    return minus_to_int(y1, y2)


def get_angle_base_negative(point):
    x, y = point
    angle = numpy.arcsin(y)       # y / 1

    if x > 0:
        return angle

    if y > 0:
        # 关于π/2 对称
        # print("second angle ", angle)
        return math.pi - angle
    else:
        # 关于-π/2 对称
        assert angle < 0
        return -math.pi - angle

def get_angle_base_0(point):
    x, y = point
    angle = get_angle_base_negative(point)
    if y > 0:
        return angle
    else:
        return angle + pi2


def in_half_circle(a1, a2):
    return a2 - a1 < math.pi

def one_pariment(num):
    # 一次试验
    points = n_circle_point(num)
    clockwise_points = sorted(points, cmp=point_cmp)

    angle1 = get_angle_base_0(clockwise_points[0])
    angle2 = get_angle_base_0(clockwise_points[-1])
    # print(angle1, angle2)
    if in_half_circle(angle1, angle2):
        return True

    clockwise_points = sorted(points, cmp=point_cmp_from_3)
    angle1 = get_angle_base_negative(clockwise_points[0])
    angle2 = get_angle_base_negative(clockwise_points[-1])
    # print(angle1, angle2)
    return in_half_circle(angle1, angle2)

def four_point():
    cnt = 100000 * 10
    hit = 0
    num = 6
    for i in range(cnt):
        # if one_pariment(3):   # (1 + 2) / (2 ** 2)
        # if one_pariment(4):   # (1 + 3) / (2 ** 3)
        if one_pariment(num):     # (1 + 4) / (2 ** 4)
            hit += 1

    print("hit:", hit)
    print("probability:", hit / float(cnt))

    m1 = num - 1
    print("theory  :", (1 + m1) / float(2**m1))

def test():
    points = n_circle_point(4)
    print(points)
    # points = [(-1, -3), (-1, 2), (1, 2), (1, -3)]
    clockwise_points = sorted(points, cmp=point_cmp)
    print()
    print(clockwise_points)

    print()
    for point in clockwise_points:
        # 忽略x == 0的特殊情况
        if abs(point[0]-0) < 0.00000001:
            continue

        # angle = get_angle_base_negative(point)
        angle = get_angle_base_0(point)
        print(angle)
        print("==", angle * (180 / math.pi))


def main():
    print("start main")
    # test()
    four_point()

if __name__ == "__main__":
    main()
